package com.yuantu.judiciary.serviceimpl;


import com.alibaba.fastjson2.JSON;
import com.wechat.pay.java.core.Config;
import com.wechat.pay.java.core.RSAAutoCertificateConfig;
import com.wechat.pay.java.core.notification.NotificationConfig;
import com.wechat.pay.java.core.notification.NotificationParser;
import com.wechat.pay.java.core.notification.RequestParam;
import com.wechat.pay.java.service.payments.h5.H5Service;
import com.wechat.pay.java.service.payments.h5.model.H5Info;
import com.wechat.pay.java.service.payments.jsapi.JsapiService;
import com.wechat.pay.java.service.payments.jsapi.JsapiServiceExtension;
import com.wechat.pay.java.service.payments.jsapi.model.*;
import com.wechat.pay.java.service.payments.model.Transaction;
import com.wechat.pay.java.service.refund.RefundService;
import com.wechat.pay.java.service.refund.model.AmountReq;
import com.wechat.pay.java.service.refund.model.CreateRequest;
import com.wechat.pay.java.service.refund.model.QueryByOutRefundNoRequest;
import com.wechat.pay.java.service.refund.model.Refund;
import com.wechat.pay.java.service.transferbatch.TransferBatchService;
import com.wechat.pay.java.service.transferbatch.model.InitiateBatchTransferRequest;
import com.wechat.pay.java.service.transferbatch.model.InitiateBatchTransferResponse;
import com.wechat.pay.java.service.transferbatch.model.TransferDetailInput;
import com.yuantu.judiciary.model.dto.AddOrderDTO;
import com.yuantu.judiciary.model.dto.RefundOrderDTO;
import com.yuantu.judiciary.model.enums.IsShare;
import com.yuantu.judiciary.service.IApiWxPayService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpServletRequest;
import java.io.BufferedReader;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;

/**
 * 微信支付
 *
 * @author syw
 * @since 2023-08-14
 **/
@Service
@RequiredArgsConstructor
@Slf4j
public class ApiWxPayServiceImpl implements IApiWxPayService {
    /**
     * 商户号
     */
    //public static String merchantId = "1624548283";

    public static String merchantId = "1684704723";
    /**
     * 商户API私钥路径
     */
//    public static String privateKey = "-----BEGIN PRIVATE KEY-----" +
//            "MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDH2TGddjyEeiCy" +
//            "nDiE6zaRYLJNVb/iMVxWcpfCgH9BfEEgr0OgV6knQlb4AWkPwSTekY1vbNdDKCCg" +
//            "gwgF6V0Dz37cCkjtOItvy1ia0aJmqUsN8pg8l8wTPX+bl4IriHPYCVJGv5c20gHN" +
//            "e/JPKps+BJOFgQRWWOlXNB3llAjFsM4VD+034HvAUdXy/tQgSSsCQrKYekkLVumA" +
//            "gTc2xEOrFCij2zANSXUbpGvd9Y4mn8FHZ27wf691YdE/68kU2LVaL/IGVXp4TMZ6" +
//            "jxX2BqghWE5rFpLhgdIjIE0hgXRqtPKNndWoaabgcJrvPzP2IIWdobUULBIjqYTT" +
//            "+IKrjk3hAgMBAAECggEAN7TXG6lFnTfdvWvGZWabQ1LM4LmyTv6rWn1+x/zBfCOC" +
//            "k/XGx/8na4YWb/MUsguIl3HDFvgj2Nhqn9NmfR9biiBgoD1NrrJAS91GyYD939f4" +
//            "z957iQhXHlXaKCjHZBMZF3MhuA7Xu7Q2RGz0UhTySQtFg8U+zELkaCZi3wewmkn7" +
//            "a/EEZWMOvCu29WL4tZRbpfj8s3ce6hw+fYjydtStADYWP+iAmH5jnvhl2dOT9UGb" +
//            "i09blTJt3ix2EymkjrAamPJfngS914n+kr8Aibv5DSOA8dLUYYz/ZSRo2HwuF8/S" +
//            "bvOSog25vNKAnIlhzlB2TawkbW8e3TbleS4DBn8BQQKBgQD+oH2uHZBWi+YhJEsp" +
//            "OLvFI7wnu5Q9DxBCvxhfIpxDNVSEUQpT/Wq2qCwcioP8MEg/TITw4C/BgieLgPu2" +
//            "SLITxc/4YMM+NgTbTUcsTKXZcstKQTIT1v+3UuXSW+UWZv5x7Hc3ZK6/mAXMo6M5" +
//            "dcAVqvJItMLrBPwED5tEbkPYnQKBgQDI7RT13LeQVdnPIzRlG/K6FhED4LZ6u0PI" +
//            "wWrcraUeC1Bzo/Gk8lf84GIZ0ahsHSpfcA25z1EtALQ+PWZ2yzBPgFmTvAtCMl0i" +
//            "Njo+2pYwJQq3hNDYqqLTwzoA112bOdWjHr2M3W0MBM/2uVXvEhYLaad9gNNQw3Pl" +
//            "xp0WCpbdFQKBgQDQXYk7eJnrGOSjbk3LV8/gjVOluAygwrjtxe8tuubg4L1e4epv" +
//            "vMsc2hXu7TMApooYsod/jhXGZrnxoQVar7Z6E8ASYyyithXXWC/MApUdkqDlDODr" +
//            "916fKElFkUmwwWuq0nTkcZHG26KzSZ2CoeckVBWchb+UDyokMJlAsHL4yQKBgHoT" +
//            "YWrHwVeWcZFiaFEOG/lnssrSWsxSvqpYqZ6OegW5BhZcg1KeU0s24SOiuFuHlNkL" +
//            "cat1BHL9PIWcNIb0iNOkvcf+tjBv/RnuLJFHqXxy5QH/VgxuECPtN26PazYGe4By" +
//            "CuRtG/Xzbo8Op+Fq8a3ZcYPVI46sUdxHQeXEZUjJAoGAU/yXwb/7KwcfWL4YLSZz" +
//            "RvCT0+vHTisQ4eDcUUk/A5P1dEXVPCWjIlpzEEkxE0fUvmKkgxUF3v1OC4GQBAZf" +
//            "csGh/Aie6m1hpHlpQR2R25ePB51TYDcX/S5nFho/YF+iByRCoItQEwQp4yf2VHRM" +
//            "p7RbBJgmw/6AvMt3TcPt2/M=" +
//            "-----END PRIVATE KEY-----";

    public static String privateKey = "-----BEGIN PRIVATE KEY-----" +
            "MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCmu9kecjD6OqPH" +
            "cGNxtd5HjlgOANcs51CYPVvt0O63WyAQCJs5fNF2LzABbgTJe88rG8gqAnuNFHP/" +
            "rivV7bLABHhV3FQONXu/GO5teyySzcyh1Pl9bC2NZ1uMzpHWk6L1vFA6tOcmjPqo" +
            "azPBsJvKuaZsSk0iKAO7oSeKj768xKQQNb+yNlbA1kQ1kLm9O8seoeBzIsSdAXip" +
            "gBm6oKwZvpQ/LPObv/v7cAd6qdh4q38smFwmt7MSp2CHWejG3+Rd2n5MrpekQ3jn" +
            "OIZsJ0kSSapl9Fo0Zjg7PUKN9B+9LgakmIvSlitHe4mCEjmYc+FyIqRwwCUDeloB" +
            "Fj2D/CVRAgMBAAECggEAHa3+ni7RjRl3If9dlFY9dRtfjU6U/wdGD3OMs66nb7gm" +
            "4vPFPdx8JL+NmhONgpgpbpEJdoDuoVRsuay1XOVtFkU1boND6yuWFZRIjPCKJK/B" +
            "p2UT7EGfcjZd05jJ2Rp6vaeB2JFvPCuISwaaNfZMJTAa8dfgFx5sW6/6K+4ek9db" +
            "kta82wmz2CP/KTVIR4n1pFcqH2DbdxVWpmc7teO45KgJVHs9vyGwdaE4rJBpUziz" +
            "bmGZHJg+0SB/I5JS23qhtQDbnwgGhMdsm8BiDn2fwnfvnRRAlmsnceKscdKF9mdf" +
            "YiyDxTZ5WGrzHU7xnhOqjy3eTQGJbM2ckzN2D0X5CQKBgQDTK0G93sGa+CYGV/mb" +
            "IUQhu6gFn3MTq2BnEWZDyPdeeIsZAx1lcrovWJKVpx0C6SGNHWrqi1wxc9zv2AT4" +
            "YpqK0cHeVUUGxvBehOABkUZKG07IEJTm29OKOkFQp+K+2IBQhJFhhEQ55qzd/8Of" +
            "ZQotCdwSCiZwFHA07cUf/ZnE1wKBgQDKIZmPahFwYy2whOHqlWw/K6i9O/yyTkJz" +
            "miqN/I7dh+atYzJPTdt0yXMkBGr0d0/d+ocH4Dtv2/xsS2j8jZS3sgwPI0OzQVjd" +
            "qTQYkEaita5XXHEZ19q/ReLVZ4RTkyYZ+xOK/2dZHD9XXp/oKvVMl9dTnxaPLrLd" +
            "Y15BDut6FwKBgQCtnXDtpElVGhRZPtdvXchgW6LnDJNWZp5Z3wpPTNlkiIMES3VN" +
            "xSeiaZYLCFxn2jjFhpwyveVMm0/YuahMdvVMkOxt2Xlo+wMBEwoA/+nkX9ND1a42" +
            "qCGiEgdFQuK/ucy1ZmkI3fAiEq+pzfCOCkp1gRe4lTPJDmS6f4qEpMJZ/QKBgHRS" +
            "X7/Dp6OIv9tsrWJFeVTlOCcmpWarWNyUJNcvN7xPIDY59tLimF+eKs/YZwCmxOSW" +
            "7yxeI3ZdH+fmgdWNWL9aDEyN28EF4zE01ZEpPi0W5uzJeyEHMpCOlFqBRwqdjPi4" +
            "n+eG0Z/bfKw3/UgrqJzaaQVrcR0XH8H+FFjWUDcjAoGAUlI4IP5FrOd/1ZD7C2zj" +
            "q6tPwdkcv1pJsJ7Pv0TznwKNWI3BqDz9lB3kOanta7bXPImp5mdZEUvlnbU+HxUH" +
            "ZMeNADS6RmZg0e2K5Ba82iMza/6xaKAzZjHAoBeHz2qjipeOIxeisKMAoo0nulJi" +
            "QQr1VHaEAzLKqbd9/XHpsIM=" +
            "-----END PRIVATE KEY-----";

    /**
     * 商户证书序列号
     */
   // public static String merchantSerialNumber = "7105493EC573E58D3B344CC26B23A91827BD62BA";

    public static String merchantSerialNumber = "3ADCDE069AA8A2EFF57D93C8E89534E13E32F3CB";

    /**
     * 商户APIV3密钥
     */
    //public static String apiV3Key = "5lbkidpdepm1r8rhkd4i9plmhd32sg7i";

    public static String apiV3Key = "Nanjingxuanyingwangluokeji201404";
    /**
     * appid
     */
    private static String appid = "wxeccb8103bee7b465";

    public static Config config;

    public void getConfig() {
        if (config == null) {
            config = new RSAAutoCertificateConfig.Builder()
                    .merchantId(merchantId)
                    .privateKey(privateKey)
                    .merchantSerialNumber(merchantSerialNumber)
                    .apiV3Key(apiV3Key)
                    .build();
        }
    }

    @Override
    public PrepayResponse addOrder(AddOrderDTO data) {
        getConfig();
        JsapiService service = new JsapiService.Builder().config(config).build();
        PrepayRequest request = new PrepayRequest();
        Amount amount = new Amount();
        amount.setTotal((int) Math.round(data.getTotalPrice() * 100));
        request.setAmount(amount);
        request.setAppid(appid);
        request.setMchid(merchantId);
        request.setDescription(data.getName());
//        request.setNotifyUrl("https://cxb.learncoder.com:8901/api/order/notify");
        //request.setNotifyUrl("https://admin.njxnet.com:8901/api/order/notify");
        if(IsShare.YES.getValue().equals(data.getType())){
            request.setNotifyUrl("https://admin.njxnet.com:8901/api/order/notify/share");
        }else {
            request.setNotifyUrl("https://admin.njxnet.com:8901/api/order/notify");
        }
        request.setOutTradeNo(data.getTradeNo());
        Payer payer = new Payer();
        payer.setOpenid(data.getOpenId());
        request.setPayer(payer);
        return service.prepay(request);
    }

    @Override
    public PrepayWithRequestPaymentResponse getParam(AddOrderDTO data) {
        getConfig();
        JsapiServiceExtension service = new JsapiServiceExtension.Builder().config(config).build();
        PrepayRequest request = new PrepayRequest();
        Amount amount = new Amount();
        ;
        amount.setTotal((int) Math.round(data.getTotalPrice() * 100));
        request.setAmount(amount);
        request.setAppid(appid);
        request.setMchid(merchantId);
        request.setDescription(data.getName());
//        request.setNotifyUrl("https://cxb.learncoder.com:8901/api/order/notify");
        //request.setNotifyUrl("https://admin.njxnet.com:8901/api/order/notify");
        if(IsShare.YES.getValue().equals(data.getType())){
            request.setNotifyUrl("https://admin.njxnet.com:8901/api/order/notify/share");
        }else {
            request.setNotifyUrl("https://admin.njxnet.com:8901/api/order/notify");
        }
        request.setOutTradeNo(data.getTradeNo());
        Payer payer = new Payer();
        payer.setOpenid(data.getOpenId());
        request.setPayer(payer);
        return service.prepayWithRequestPayment(request);
    }

    @Override
    public Transaction callOrder(HttpServletRequest request) {
        getConfig();

        try {
            BufferedReader br = request.getReader();
            String str;
            StringBuilder sb = new StringBuilder();
            while ((str = br.readLine()) != null) {
                sb.append(str);
            }
            String timestamp = request.getHeader("Wechatpay-Timestamp");
            String nonce = request.getHeader("Wechatpay-Nonce");
            String signature = request.getHeader("Wechatpay-Signature");
            String signType = request.getHeader("Wechatpay-Signature-Type");
            String wechatPayCertificateSerialNumber = request.getHeader("Wechatpay-Serial");

            // 构造 RequestParam
            RequestParam requestParam = new RequestParam.Builder()
                    .serialNumber(wechatPayCertificateSerialNumber)
                    .nonce(nonce)
                    .signature(signature)
                    .timestamp(timestamp)
                    .body(String.valueOf(sb))
                    .build();
            log.info("支付回调构造参数: {}", sb);

            // 初始化 NotificationParser
            NotificationParser parser = new NotificationParser((NotificationConfig) config);

            // 以支付通知回调为例，验签、解密并转换成 Transaction
            return parser.parse(requestParam, Transaction.class);

        } catch (Exception e) {
            log.error("支付回调异常: " + e.getMessage(), e);
        }

        return null;
    }

    @Override
    public Refund executeRefund(RefundOrderDTO data) {
        getConfig();
        RefundService service = new RefundService.Builder().config(config).build();
        CreateRequest request = new CreateRequest();
        request.setOutTradeNo(data.getTradeNo());
        request.setOutRefundNo(data.getRefundNo());
        AmountReq amount = new AmountReq();
        amount.setRefund(Math.round(data.getTotalPrice() * 100));
        amount.setTotal(Math.round(data.getTotalPrice() * 100));
        amount.setCurrency("CNY");
        request.setAmount(amount);
        Refund refund = null;
        try {
            refund = service.create(request);
        } catch (Exception e) {
            log.error("[微信小程序] 订单：{} 退款金额变更异常", data.getTradeNo(), e);
        }
        return refund;
    }

    @Override
    public Refund queryRefund(String refundNo) {
        getConfig();
        RefundService service = new RefundService.Builder().config(config).build();
        QueryByOutRefundNoRequest request = new QueryByOutRefundNoRequest();
        request.setOutRefundNo(refundNo);
        Refund refund = null;
        try {
            refund = service.queryByOutRefundNo(request);
        } catch (Exception e) {
            log.error("[微信小程序] 退款单号：{} 退款信息查询异常", refundNo, e);
        }
        return refund;
    }

    @Override
    public InitiateBatchTransferResponse executeTransfer(Long exTractPointId) {

        getConfig();
        TransferBatchService service = new TransferBatchService.Builder().config(config).build();
        InitiateBatchTransferRequest request = new InitiateBatchTransferRequest();
        request.setAppid(appid);
        request.setOutBatchNo(UUID.randomUUID().toString().replace("-", ""));
        request.setBatchName("test_transfer");
        request.setBatchRemark("测试转账");
        request.setTotalAmount(1L);
        request.setTotalNum(1);
        TransferDetailInput detailInput = new TransferDetailInput();
        detailInput.setOpenid("oErp06zfEnnA0PP6_ywGbnGlSVq4");
        detailInput.setOutDetailNo(UUID.randomUUID().toString().replace("-", ""));
        detailInput.setTransferAmount(1L);
        detailInput.setTransferRemark("hahaha");
        List<TransferDetailInput> detailInputList = new ArrayList<>();
        detailInputList.add(detailInput);
        request.setTransferDetailList(detailInputList);
        InitiateBatchTransferResponse response = service.initiateBatchTransfer(request);
        System.out.println(JSON.toJSONString(response));
        return response;
    }

    @Override
    public  com.wechat.pay.java.service.payments.h5.model.PrepayResponse addPageOrder(AddOrderDTO data) {
        getConfig();
        H5Service h5Service  = new H5Service.Builder().config(config).build();
        com.wechat.pay.java.service.payments.h5.model.PrepayRequest request = new  com.wechat.pay.java.service.payments.h5.model.PrepayRequest();
        com.wechat.pay.java.service.payments.h5.model.Amount amount = new com.wechat.pay.java.service.payments.h5.model.Amount();
        amount.setTotal((int) Math.round(data.getTotalPrice() * 100));
        request.setAmount(amount);
        request.setAppid(appid);
        request.setMchid(merchantId);
        request.setDescription(data.getName());
        request.setOutTradeNo(data.getTradeNo());
        request.setNotifyUrl("https://admin.njxnet.com:8901/api/order/notify/share");
        com.wechat.pay.java.service.payments.h5.model.SceneInfo sceneInfo = new com.wechat.pay.java.service.payments.h5.model.SceneInfo();
        sceneInfo.setPayerClientIp(data.getIpInfo());
        H5Info h5Info = new H5Info();
        h5Info.setType(data.getType());
        sceneInfo.setH5Info(h5Info);
        request.setSceneInfo(sceneInfo);
        return h5Service.prepay(request);
    }


}
